﻿
using System.Text;

using TTGIS.TileServer.API.ApiModels;
using TTGIS.TileServer.API.ApiModels.Common;

namespace TTGIS.TileServer.API.MapInfoFiles
{
    /// <summary>
    ///Mif文件解析服务
    /// </summary> 
    public class GetDataFromFile
    {
        /// <summary>
        /// 获取数据
        /// </summary>
        /// <param name="mifFilePath">信息地址</param>
        /// <param name="midFilePath">数据文件</param>
        /// <param name="midEncoding">数据文件编码</param>
        public GetDataInfoFromMifResponse GetData(string mifFilePath, string midFilePath, string midEncoding)
        {
            using var file = File.OpenText(mifFilePath);
            using var midFile = File.OpenRead(midFilePath);
            var bytes = new byte[midFile.Length];
            _ = midFile.Read(bytes);
            midFile.Close();
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            var midInfo = Encoding.GetEncoding(midEncoding).GetString(bytes);
            var db = midInfo.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);

            string charSet = "WindowsSimpChinese";
            string delimiter = "\t";
            var columns = new List<string>();
            string? s = "";

            var result = new GetDataInfoFromMifResponse();

            var index = 0;
            while ((s = file.ReadLine()) != null)
            {
                if (s.StartsWith("Charset", StringComparison.OrdinalIgnoreCase))
                {
                    charSet = s[(s.IndexOf('\"') + 1)..s.LastIndexOf('\"')];
                }
                if (s.StartsWith("CoordSys", StringComparison.OrdinalIgnoreCase))
                {
                    result.CoordSys = s[(s.IndexOf(' ') + 1)..];
                }
                if (s.StartsWith("delimiter", StringComparison.OrdinalIgnoreCase))
                {
                    delimiter = s[(s.IndexOf(' ') + 1)..].Replace("\"", "");
                }

                if (s.StartsWith("Columns", StringComparison.OrdinalIgnoreCase))
                {
                    var count = Convert.ToInt32(s[(s.IndexOf(' ') + 1)..]);
                    for (int i = 0; i < count; i++)
                    {
                        s = file.ReadLine();
                        columns.Add(s[..(s.LastIndexOf(' '))].Trim());
                    }
                }
                if (s.StartsWith("Data", StringComparison.OrdinalIgnoreCase))
                {
                    break;
                }
            }

            while ((s = file.ReadLine()) != null)
            {
                if (s.StartsWith("Roundrect", StringComparison.OrdinalIgnoreCase))
                {
                    var gItem = new Roundrect();
                    var info = s.Replace("Roundrect", "").Split(' ', StringSplitOptions.RemoveEmptyEntries);
                    for (int i = 0; i < info.Length - 1;)
                    {
                        var location = new LocationInfo() { X = Convert.ToDouble(info[i++]), Y = Convert.ToDouble(info[i++]) };
                        if (i == 2)
                        {
                            gItem.LeftTop = location;
                        }
                        else
                        {
                            gItem.RightBottom = location;
                        }
                    }
                    if (Double.TryParse(info[info.Length - 1], out var res))
                    {
                        gItem.Radian = res;
                    }

                    var dbStrs = db[index].Replace("\"", "").Split(new string[] { delimiter }, StringSplitOptions.None);
                    for (int i = 0; i < columns.Count; i++)
                    {
                        gItem.DBData.Add(columns[i], dbStrs[i]);
                    }
                    index++;
                    result.Items.Add(gItem);
                }
                else if (s.StartsWith("Line", StringComparison.OrdinalIgnoreCase))
                {
                    var gItem = new Line();
                    var info = s.Replace("Line", "").Split(' ', StringSplitOptions.RemoveEmptyEntries)[..4];
                    for (int i = 0; i < info.Length;)
                    {
                        var location = new LocationInfo() { X = Convert.ToDouble(info[i++]), Y = Convert.ToDouble(info[i++]) };
                        if (i == 2)
                        {
                            gItem.Left = location;
                        }
                        else
                        {
                            gItem.Right = location;
                        }
                    }
                    var dbStrs = db[index].Replace("\"", "").Split(new string[] { delimiter }, StringSplitOptions.None);
                    for (int i = 0; i < columns.Count; i++)
                    {
                        gItem.DBData.Add(columns[i], dbStrs[i]);
                    }
                    index++;
                    result.Items.Add(gItem);
                }
                else if (s.StartsWith("Arc", StringComparison.OrdinalIgnoreCase))
                {
                    var gItem = new Arc();
                    var info = s.Replace("Arc", "").Split(' ', StringSplitOptions.RemoveEmptyEntries);
                    for (int i = 0; i < info.Length;)
                    {
                        var location = new LocationInfo() { X = Convert.ToDouble(info[i++]), Y = Convert.ToDouble(info[i++]) };
                        if (i == 2)
                        {
                            gItem.LeftTop = location;
                        }
                        else
                        {
                            gItem.RightBottom = location;
                            break;
                        }
                    }
                    if (Double.TryParse(info[info.Length - 2], out var sa))
                    {
                        gItem.StartRadian = sa;
                    }
                    if (Double.TryParse(info[info.Length - 1], out var ea))
                    {
                        gItem.StopRadian = ea;
                    }
                    var dbStrs = db[index].Replace("\"", "").Split(new string[] { delimiter }, StringSplitOptions.None);
                    for (int i = 0; i < columns.Count; i++)
                    {
                        gItem.DBData.Add(columns[i], dbStrs[i]);
                    }
                    index++;
                    result.Items.Add(gItem);
                }
                else if (s.StartsWith("Point", StringComparison.OrdinalIgnoreCase))
                {
                    var gItem = new Point();
                    var info = s.Replace("Point", "").Split(' ', StringSplitOptions.RemoveEmptyEntries);
                    for (int i = 0; i < info.Length;)
                    {
                        gItem.Location = new LocationInfo() { X = Convert.ToDouble(info[i++]), Y = Convert.ToDouble(info[i++]) };
                    }
                    var dbStrs = db[index].Replace("\"", "").Split(new string[] { delimiter }, StringSplitOptions.None);
                    for (int i = 0; i < columns.Count; i++)
                    {
                        gItem.DBData.Add(columns[i], dbStrs[i]);
                    }
                    index++;
                    result.Items.Add(gItem);
                }
                else if (s.StartsWith("Rect", StringComparison.OrdinalIgnoreCase))
                {
                    var gItem = new Rect();
                    var info = s.Replace("Rect", "").Split(' ', StringSplitOptions.RemoveEmptyEntries);
                    for (int i = 0; i < info.Length;)
                    {
                        var location = new LocationInfo() { X = Convert.ToDouble(info[i++]), Y = Convert.ToDouble(info[i++]) };
                        if (i == 2)
                        {
                            gItem.LeftTop = location;
                        }
                        else
                        {
                            gItem.RightBottom = location;
                            break;
                        }
                    }
                    var dbStrs = db[index].Replace("\"", "").Split(new string[] { delimiter }, StringSplitOptions.None);
                    for (int i = 0; i < columns.Count; i++)
                    {
                        gItem.DBData.Add(columns[i], dbStrs[i]);
                    }
                    index++;
                    result.Items.Add(gItem);
                }
                else if (s.StartsWith("Ellipse", StringComparison.OrdinalIgnoreCase))
                {
                    var gItem = new Ellipse();
                    var info = s.Replace("Ellipse", "").Split(' ', StringSplitOptions.RemoveEmptyEntries);
                    for (int i = 0; i < info.Length;)
                    {
                        var location = new LocationInfo() { X = Convert.ToDouble(info[i++]), Y = Convert.ToDouble(info[i++]) };
                        if (i == 2)
                        {
                            gItem.LeftTop = location;
                        }
                        else
                        {
                            gItem.RightBottom = location;
                            break;
                        }
                    }
                    var dbStrs = db[index].Replace("\"", "").Split(new string[] { delimiter }, StringSplitOptions.None);
                    for (int i = 0; i < columns.Count; i++)
                    {
                        gItem.DBData.Add(columns[i], dbStrs[i]);
                    }
                    index++;
                    result.Items.Add(gItem);
                }
                else if (s.StartsWith("Pline", StringComparison.OrdinalIgnoreCase))
                {
                    var gItem = new PLine();
                    var info = Convert.ToInt32(s.Replace("Pline", "").Trim());
                    for (int i = 0; i < info; i++)
                    {
                        s = file.ReadLine();
                        var items = s.Split(' ', StringSplitOptions.RemoveEmptyEntries);

                        gItem.Points.Add(new LocationInfo()
                        {
                            X = Convert.ToDouble(items[0]),
                            Y = Convert.ToDouble(items[1]),
                        });
                    }
                    var dbStrs = db[index].Replace("\"", "").Split(new string[] { delimiter }, StringSplitOptions.None);
                    for (int i = 0; i < columns.Count; i++)
                    {
                        gItem.DBData.Add(columns[i], dbStrs[i]);
                    }
                    index++;
                    result.Items.Add(gItem);
                }
                else if (s.StartsWith("Region", StringComparison.OrdinalIgnoreCase))
                {
                    var gItem = new Region();
                    s = file.ReadLine();
                    var info = Convert.ToInt32(s.Trim());
                    for (int i = 0; i < info; i++)
                    {
                        s = file.ReadLine();
                        var items = s.Split(' ', StringSplitOptions.RemoveEmptyEntries);

                        gItem.Points.Add(new LocationInfo()
                        {
                            X = Convert.ToDouble(items[0]),
                            Y = Convert.ToDouble(items[1]),
                        });
                    }
                    var dbStrs = db[index].Replace("\"", "").Split(new string[] { delimiter }, StringSplitOptions.None);
                    for (int i = 0; i < columns.Count; i++)
                    {
                        gItem.DBData.Add(columns[i], dbStrs[i]);
                    }
                    index++;
                    result.Items.Add(gItem);
                }
                else if (s.StartsWith("Text", StringComparison.OrdinalIgnoreCase))
                {
                    var gItem = new Text();

                    s = file.ReadLine();
                    gItem.TextInfo = s.Trim().Replace('\"', ' ').Trim();
                    s = file.ReadLine();
                    var info = s.Split(' ', StringSplitOptions.RemoveEmptyEntries);
                    for (int i = 0; i < info.Length;)
                    {
                        var location = new LocationInfo() { X = Convert.ToDouble(info[i++]), Y = Convert.ToDouble(info[i++]) };
                        if (i == 2)
                        {
                            gItem.LeftTop = location;
                        }
                        else
                        {
                            gItem.RightBottom = location;
                        }
                    }
                    var dbStrs = db[index].Replace("\"", "").Split(new string[] { delimiter }, StringSplitOptions.None);
                    for (int i = 0; i < columns.Count; i++)
                    {
                        gItem.DBData.Add(columns[i], dbStrs[i]);
                    }
                    index++;
                    result.Items.Add(gItem);
                }
            }

            return result;
        }
    }
}
